home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1998 September
/
Macworld (1998-09).dmg
/
Shareware World
/
Info
/
For Developers
/
MacZoop 1.8.3
/
Required Classes
/
Z Sources
/
ZComrade.cpp
< prev
next >
Wrap
Text File
|
1998-06-11
|
8KB
|
313 lines
/*************************************************************************************************
*
*
* MacZoop - "the framework for the rest of us"
*
*
*
* ZComrade.cpp -- an object that can maintain loose links between objects
*
*
*
*
*
* © 1996, Graham Cox
*
*
*
*
*************************************************************************************************/
#include "ZComrade.h"
#include "ZObjectArray.cpp"
#include "MacZoop.h"
// this is a fudge to get around a limitation of the language- ZComrade requires ZObjectArray
// for its lists, but ZObjectArray IS a ZComrade. Thus, since we are not allowed forward/
// circular cross-dependencies like this, this struct is used to "pull" the declaration forward
// so that everything compiles correctly.
struct ZComradeList : ZObjectArray<ZComrade>
{
};
CLASSCONSTRUCTOR( ZComrade );
/*---------------------------------*** CONSTRUCTOR ***--------------------------------*/
ZComrade::ZComrade()
{
classID = CLASS_ZComrade;
talkers = listeners = NULL;
}
/*---------------------------------*** DESTRUCTOR ***---------------------------------*/
ZComrade::~ZComrade()
{
// when we are destroyed, we need to make sure that we remove ourselves
// from any talker's list that we are part of, and make sure that any listeners
// that are listening to us no longer do so.
long n;
ZComrade* aComrade;
if( listeners )
{
n = listeners->CountItems();
do
{
aComrade = listeners->GetObject( n );
if( aComrade )
aComrade->RemoveTalker( this );
}
while( --n );
ForgetObject( listeners );
}
if( talkers )
{
n = talkers->CountItems();
do
{
aComrade = talkers->GetObject( n );
if( aComrade )
aComrade->RemoveListener( this );
}
while( --n );
ForgetObject( talkers );
}
}
/*--------------------------------*** SENDMESSAGE ***---------------------------------*/
/*
transmit a message to anyone who is listening
----------------------------------------------------------------------------------------*/
void ZComrade::SendMessage( long aMessage, void* msgData )
{
// send the message to all of the listeners of this object
long n;
ZComrade* aListener;
if( listeners )
{
n = listeners->CountItems();
do
{
aListener = listeners->GetObject( n );
if( aListener )
aListener->ReceiveMessage( this, aMessage, msgData );
}
while( --n );
}
}
/*--------------------------------*** SENDMESSAGE ***---------------------------------*/
/*
transmit a message to anyone who is listening (via a message object)
----------------------------------------------------------------------------------------*/
void ZComrade::SendMessage( ZMessage* aMessage )
{
// send the message object to all of the listeners of this object
long n;
ZComrade* aListener;
if( listeners )
{
n = listeners->CountItems();
do
{
aListener = listeners->GetObject( n );
if( aListener )
aListener->ReceiveMessage( this, aMessage );
}
while( --n );
}
}
/*-------------------------------*** RECEIVEMESSAGE ***-------------------------------*/
/*
a message was transmitted by someone we have earlier elected to listen to
----------------------------------------------------------------------------------------*/
void ZComrade::ReceiveMessage( ZComrade* aSender, long theMessage, void* msgData )
{
// override to do something useful
}
/*------------------------------*** RECEIVEMESSAGE ***--------------------------------*/
/*
receive a message in a message object from one of our transmitting comrades
----------------------------------------------------------------------------------------*/
void ZComrade::ReceiveMessage( ZComrade* aSender, ZMessage* aMessage )
{
// override to do something useful
}
/*---------------------------------*** LISTENTO ***-----------------------------------*/
/*
elect to listen to another comrade. We will receive any messages transmitted by that
object whenever it sends them
----------------------------------------------------------------------------------------*/
void ZComrade::ListenTo( ZComrade* aSender )
{
// add this to the sender's list of listeners, and the sender to our list of talkers
FailOSErr((aSender == NULL)? paramErr : noErr );
// make sure we are not already listening to this one- references must be
// included exactly once
if(( talkers == NULL ) || !talkers->Contains( aSender ))
{
aSender->AddListener( this );
AddTalker( aSender );
}
}
/*-----------------------------*** STOPLISTENINGTO ***-------------------------------*/
/*
we no longer want to receive messages from this transmitter
----------------------------------------------------------------------------------------*/
void ZComrade::StopListeningTo( ZComrade* aSender )
{
// remove this from the sender's list of listeners, and remove it from our list of talkers
FailOSErr((aSender == NULL)? paramErr : noErr );
// make sure we are really listening to it
if (talkers && talkers->Contains( aSender ))
{
RemoveTalker( aSender );
aSender->RemoveListener( this );
}
}
/*---------------------------------*** ADDTALKER ***----------------------------------*/
/*
add a talker to our list of talkers
----------------------------------------------------------------------------------------*/
void ZComrade::AddTalker( ZComrade* aTalker )
{
// add the talker to the list of talkers
if (talkers == NULL)
FailNIL( talkers = new ZComradeList());
talkers->AppendItem( aTalker );
}
/*-------------------------------*** ADDLISTENER ***----------------------------------*/
/*
add a listener to our list of listeners
----------------------------------------------------------------------------------------*/
void ZComrade::AddListener( ZComrade* aListener )
{
// add the listener to the list of listeners
if (listeners == NULL)
FailNIL( listeners = new ZComradeList());
listeners->AppendItem( aListener );
}
/*--------------------------------*** REMOVETALKER ***--------------------------------*/
/*
remove the talker from our list of talkers
----------------------------------------------------------------------------------------*/
void ZComrade::RemoveTalker( ZComrade* aTalker )
{
// remove this talker from the list of talkers
if( talkers )
{
talkers->DeleteObject( aTalker );
if( talkers->CountItems() <= 0 )
ForgetObject( talkers );
}
}
/*-------------------------------*** REMOVELISTENER ***-------------------------------*/
/*
remove the listener from our list of listeners
----------------------------------------------------------------------------------------*/
void ZComrade::RemoveListener( ZComrade* aListener )
{
// remove this listener from the list of listeners
if( listeners )
{
listeners->DeleteObject( aListener );
if( listeners->CountItems() <= 0 )
ForgetObject( listeners );
}
}
/*--------------------------------*** WRITETOSTREAM ***-------------------------------*/
/*
write talkers and listener refs to stream
----------------------------------------------------------------------------------------*/
void ZComrade::WriteToStream( ZStream* aStream )
{
#if _MACZOOP_STREAMS
// note: ZStream permits NULL objects to be written to the stream, so we don't even
// need to check whether they're NULL or not.
aStream->WriteObject( talkers );
aStream->WriteObject( listeners );
#endif
}
/*-------------------------------*** READFROMSTREAM ***-------------------------------*/
/*
read from the stream- this re-establishes the entire comrade linkage from the stream.
You should only call this when this comrade is first made, since any existing talkers
or listeners objects will be left dangling.
----------------------------------------------------------------------------------------*/
void ZComrade::ReadFromStream( ZStream* aStream )
{
#if _MACZOOP_STREAMS
talkers = (ZComradeList*) aStream->ReadObject();
listeners = (ZComradeList*) aStream->ReadObject();
#endif
}